/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package MeteoCal.bean;

import MeteoCal.manager.EventManager;
import MeteoCal.manager.NotificationManager;
import MeteoCal.manager.UserManager;
import MeteoCal.manager.WeatherManager;
import MeteoCal.entity.Event;
import MeteoCal.entity.Notification;
import MeteoCal.entity.Receivednotification;
import MeteoCal.entity.Weatherforecast;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;

/**
 *
 * @authors Guttadoro, Iommazzo, Saullo
 */

@ManagedBean(name="notificationBean")
@ApplicationScoped
public class NotificationBean{

    @EJB
    private NotificationManager nm;  
    @EJB
    private EventManager em;
    @EJB
    private WeatherManager wm;
    @EJB
    private UserManager um;
  
    
    private List<Receivednotification> notifications;        
    private List<Receivednotification> periodicallyUpdate;
    private List<Receivednotification> oneDayBefore;
    private List<Receivednotification> threeDaysBefore;
    private List<Receivednotification> readNotifications; 
    private List<Receivednotification> participantNotifications;        
          
    private Map<String, Receivednotification> selectedNotification;
    private Map<String, Receivednotification> selectedPeriodicallyUpdate;
    private Map<String, Receivednotification> selectedOneDayBefore;
    private Map<String, Receivednotification> selectedThreeDaysBefore;
    private Map<String, Receivednotification> selectedReadNotification;
    private Map<String, Receivednotification> selectedParticipantNotification;

    @PostConstruct
    public void init() {
        notifications =  nm.findNotRead(um.getLoggedUser().getEmail());  // sarebbe da mettere nm.findByUser(um.getLoggedUser());
        readNotifications = nm.findRead(um.getLoggedUser().getEmail()); // sarebbe da mettere getLoggerUser()
        periodicallyUpdate = new ArrayList<>();
        oneDayBefore= new ArrayList<>();
        threeDaysBefore = new ArrayList<>(); 
        participantNotifications = new ArrayList<>();  
        
        if(selectedNotification == null){
            selectedNotification = new ConcurrentHashMap<>();
            selectedPeriodicallyUpdate = new ConcurrentHashMap<>();
            selectedOneDayBefore = new ConcurrentHashMap<>();
            selectedThreeDaysBefore = new ConcurrentHashMap<>(); 
            selectedReadNotification = new ConcurrentHashMap<>();
            selectedParticipantNotification = new ConcurrentHashMap<>();
            
        }
            
         if(notifications != null){
            for(Receivednotification n : notifications){
                switch (n.getNotification().getText()){
                    case Notification.PERIODICALLY_UPDATE:
                        periodicallyUpdate.add(n);
                        break;
                    case Notification.ONE_DAY_BEFORE:
                        oneDayBefore.add(n);
                        break;
                    case Notification.THREE_DAYS_BEFORE:
                        threeDaysBefore.add(n);
                        break;
                    case Notification.E_PARTICIPANT:
                        participantNotifications.add(n);
                        break;
                }
            }
        
        }
    }
    
    public void changeWeatherEvent(){
        Receivednotification selectedThreeDays = selectedThreeDaysBefore.get(um.getLoggedUser().getEmail());
        if(selectedThreeDays.getNotification().getClosedToEvent() != null){
            Event event = selectedThreeDays.getNotification().getIdEvent();
            Date suggestedDate = selectedThreeDays.getNotification().getClosedToEvent();

            Date newDateEnd = getDifferenceBetweenDateBeginEnd(event.getDateBegin(), suggestedDate, event.getDateEnd());
            System.err.println(event.getDateBegin().toString() + suggestedDate.toString() +event.getDateEnd().toString() );
            event.setDateBegin(suggestedDate);//non funziona il cambiamento di data

            
            event.setDateEnd(newDateEnd);
            
            if(em.overlapping(um.getLoggedUser(), event) == null){
                em.edit(event);
            }
            else{
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Warning!", "The change cannot be applied due to overlapping!"));

            }
            Receivednotification rn = nm.findByIdAndUSer(selectedThreeDays.getNotification().getIdNotification(), um.getLoggedUser().getEmail());
            rn.setReadn(true);
            nm.editRn(rn);
            threeDaysBefore.remove(selectedThreeDays);
            readNotifications.add(selectedThreeDays);
            if (wm.findWeatherByCityAndDate(event.getCity(),event.getDateBegin()) == null)
                wm.createWeather(event);
            //return "user/notification?faces-redirect=true";
        }
        //return "user/notification?faces-redirect=true";

    } // aggiorna il tempo e rimuove la notifica lettsa
    
    
     public static Date getDifferenceBetweenDateBeginEnd(Date begin, Date beginNew, Date end){ 
        
        
        Long eventTimeBegin = begin.getTime();
        Long eventTimeEnd = beginNew.getTime();
        Long daysGap = eventTimeEnd - eventTimeBegin;
        daysGap = Math.round(((double)daysGap/(double)(24*3600*1000)));
        Integer days = (Integer.parseInt(daysGap.toString()));
        end.setDate(end.getDate()+days); // togli +1

        return end;
        
    }
     
     /* public static Long getDifferenceBetweenDateBeginEnd(Date begin, Date end){ 
        
        begin.setHours(0);
        begin.setMinutes(0);
        begin.setSeconds(0);
        end.setHours(0);
        end.setMinutes(0);
        end.setSeconds(0);
        Long eventTimeBegin = begin.getTime();
        Long eventTimeEnd = end.getTime();
        Long daysGap = eventTimeEnd - eventTimeBegin;
        daysGap = Math.round(((double)daysGap/(double)(24*3600*1000)));
        
        return daysGap;
    }
     
     public static Date setDateEnd(Integer daysGap, Date pastDate){
        
       /* adding dayGap to the actual date 
        Date newDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(newDate);
        calendar.add(Calendar.DATE, daysGap);
        pastDate = calendar.getTime();
        return newDate;

    }
     */ // vedi se è meglio 
     
    
    public void dontChangeWeatherEvent(){ // rimuove la notific letta
        Receivednotification selectedThreeDay = selectedThreeDaysBefore.get(um.getLoggedUser().getEmail());
        selectedThreeDay.setReadn(true);
        nm.editRn(selectedThreeDay);
        threeDaysBefore.remove(selectedThreeDay);
        readNotifications.add(selectedThreeDay);
        //return "notification?faces-redirect=true";
    }
    public Integer length(){
        return participantNotifications.size();
    }
    
    public void readParticipantNotifications(){
        Receivednotification participantDelete = selectedParticipantNotification.get(um.getLoggedUser().getEmail());
        participantDelete.setReadn(true);
        nm.editRn(participantDelete);   
        participantNotifications.remove(participantDelete);
        readNotifications.add(participantDelete);
        //return "notification?faces-redirect=true";
    } 
    
    public void readOneDayWeather(){
        Receivednotification selectedOneDay = selectedOneDayBefore.get(um.getLoggedUser().getEmail());
        selectedOneDay.setReadn(true);
        nm.editRn(selectedOneDay);   
        oneDayBefore.remove(selectedOneDay);
        readNotifications.add(selectedOneDay);
        //return "notification?faces-redirect=true";
    } 
    
    public void readPeriodicallyWeather(){
        Receivednotification selectedPeriodically = selectedPeriodicallyUpdate.get(um.getLoggedUser().getEmail());
        selectedPeriodically.setReadn(true);
        nm.editRn(selectedPeriodically);

        periodicallyUpdate.remove(selectedPeriodically);
        readNotifications.add(selectedPeriodically);
        //return "notification?faces-redirect=true"; //edit dovrebbe funzionare ma non funziona

    } 
    
    
    public Receivednotification getSelectedPeriodicallyUpdate() {
        return selectedPeriodicallyUpdate.get(um.getLoggedUser().getEmail()); // da mettere l e mail dell utente
    }

    public void setSelectedPeriodicallyUpdate(Receivednotification selectedPeriodicallyUpdate) {
        this.selectedPeriodicallyUpdate.put(um.getLoggedUser().getEmail(),selectedPeriodicallyUpdate);
    }

    public Receivednotification getSelectedOneDayBefore() {
        return selectedOneDayBefore.get(um.getLoggedUser().getEmail());
    }

    public void setSelectedOneDayBefore(Receivednotification selectedOneDayBefore) {
        this.selectedOneDayBefore.put(um.getLoggedUser().getEmail(),selectedOneDayBefore);
    }

    public Receivednotification getSelectedThreeDaysBefore() {
        return selectedThreeDaysBefore.get(um.getLoggedUser().getEmail());
    }

    public void setSelectedThreeDaysBefore(Receivednotification selectedThreeDaysBefore) {
        this.selectedThreeDaysBefore.put(um.getLoggedUser().getEmail(),selectedThreeDaysBefore);
    }

    
    public Receivednotification getSelectedNotification() {
        return selectedNotification.get(um.getLoggedUser().getEmail());
    }

    public void setSelectedNotification(Receivednotification selectedNotification) {
        this.selectedNotification.put(um.getLoggedUser().getEmail(),selectedNotification);
    }
    
    public Receivednotification getSelectedReadNotification() {
        return selectedReadNotification.get(um.getLoggedUser().getEmail());
    }

    public void setSelectedReadNotification(Receivednotification selectedReadNotification) {
        this.selectedReadNotification.put(um.getLoggedUser().getEmail(),selectedReadNotification);
    }    

    public List<Receivednotification> getPeriodicallyUpdate() {
        return periodicallyUpdate;
    }

    public void setPeriodicallyUpdate(List<Receivednotification> periodicallyUpdate) {
        this.periodicallyUpdate = periodicallyUpdate;
    }

    public List<Receivednotification> getOneDayBefore() {
        return oneDayBefore;
    }

    public void setOneDayBefore(List<Receivednotification> oneDayBefore) {
        this.oneDayBefore = oneDayBefore;
    }

    public List<Receivednotification> getThreeDaysBefore() {
        return threeDaysBefore;
    }

    public void setThreeDaysBefore(List<Receivednotification> threeDaysBefore) {
        this.threeDaysBefore = threeDaysBefore;
    }
    
    public String getIcon(String city, Date date){
        
        List<Weatherforecast> weatherforecast = wm.findWeatherByCityAndDate(city,date);
        if (weatherforecast.isEmpty())
            return "http://www.cheesium.com/idlist/index_files/unknown_icon32.png";
        return "http://openweathermap.org/img/w/"+weatherforecast.get(0).getResult_icon()+".png";


    }
    
    public String getDescription(String city, Date date){
        
        List<Weatherforecast> weatherforecast = wm.findWeatherByCityAndDate(city,date);
        if (weatherforecast.isEmpty())
            return "Unknown";
        return weatherforecast.get(0).getResult_description();
        

    }
   
    /*public String init() {
        notifications =  nm.find();    
        return "notification";
    }*/
  
    public List<Receivednotification> getNotifications() {
        return notifications;
    }

    public void setNotifications(List<Receivednotification> notifications) {
        this.notifications = notifications;
    }
    
    public List<Receivednotification> getReadNotifications() {
        return readNotifications;
    }

    public void setReadNotifications(List<Receivednotification> readNotifications) {
        this.readNotifications = readNotifications;
    }
    
    public List<Receivednotification> getParticipantNotifications() {
        return participantNotifications;
    }

    public void setParticipantNotifications(List<Receivednotification> participantNotifications) {
        this.participantNotifications = participantNotifications;
    }
    
    public void setSelectedParticipantNotification(Receivednotification selectedParticipantNotification) {
        this.selectedParticipantNotification.put(um.getLoggedUser().getEmail(),selectedParticipantNotification);
    }
    
    public Receivednotification getSelectedParticipantNotification() {
        return selectedParticipantNotification.get(um.getLoggedUser().getEmail());
    }
   
}